#include "stdafx.h"
#include "GeoObjects.h"
#include "Coordinate/CoordSys.h"

/////////////////////////////////////////////
//	CGeoLine2
/////////////////////////////////////////////

void CGeoLine2::SetStyle(int s1, int s2, int s3)
{
	// style, width, color
	m_iWidth = s1;
	m_style = s2;
	m_color = (COLORREF)s3;
}

CGeoPoint2 CGeoLine2::GetAt(size_t pos)
{
	if (pos >= 0 && pos < m_vecPts.size())
		return m_vecPts[pos];
	else
		ASSERT(0);
}

bool CGeoLine2::InWindow()
{
	double dx1 = m_rangebox.dXmin;
	double dy1 = m_rangebox.dYmin;
	double dx2 = m_rangebox.dXmax;
	double dy2 = m_rangebox.dYmax;

	bool b1 = CoordSys::InRect(dx1, dy1);
	bool b2 = CoordSys::InRect(dx2, dy2);

	if (b1 || b2)
		return true;
	
	return false;
}

void CGeoLine2::Display(CDC* pDC)
{
	if (!InWindow()) 
	{
		return;
	}

	size_t size = GetSize();
	CPoint* pts = new CPoint[size];
	for (size_t i = 0; i < size; i ++)
	{
		int x,y;
		CoordSys::Earth2Screen(GetAt(i).x, GetAt(i).y, x, y);

		pts[i].x = x;
		pts[i].y = y;
	}

	CPen Pen;  
	Pen.CreatePen(m_style, m_iWidth, m_color); 
	pDC->SelectObject(Pen);
	pDC->Polyline(pts, size);

	delete []pts;
}

RangeBox CGeoLine2::GetRangeBox(bool bRecaculate/* = false*/)
{
	if (bRecaculate)
	{
		for (size_t i = 0; i < this->GetSize(); i ++)
		{
			double dx = this->GetAt(i).x;
			double dy = this->GetAt(i).y;

			m_rangebox.dXmax = (m_rangebox.dXmax < dx) ? dx : m_rangebox.dXmax;
			m_rangebox.dXmin = (m_rangebox.dXmin > dx) ? dx : m_rangebox.dXmin;
			m_rangebox.dYmax = (m_rangebox.dYmax < dy) ? dy : m_rangebox.dYmax;
			m_rangebox.dYmin = (m_rangebox.dYmin > dy) ? dy : m_rangebox.dYmin;
		}
	}

	return m_rangebox;
}



/////////////////////////////////////////////
//	CGeoLayer
/////////////////////////////////////////////
CGeoLayer::CGeoLayer(std::string strLayerName)
{
	m_strLayerName = strLayerName;
}

CGeoLayer::~CGeoLayer(void)
{
	for (size_t i = 0; i < m_vecFeature.size(); i ++)
	{
		CGeoFeature* pFeature = m_vecFeature.at(i);
		if (pFeature)
		{
			delete pFeature;
			pFeature = NULL;
		}
	}
}

RangeBox CGeoLayer::GetRangeBox(bool bRecaculate/* = false*/)
{
	if (bRecaculate)
	{
		RangeBox featureBox;
		for (size_t i = 0; i < m_vecFeature.size(); i ++)
		{
			CGeoFeature* pFeature = (CGeoFeature*)m_vecFeature.at(i);
			if (NULL == pFeature) continue;
			featureBox = pFeature->GetRangeBox(bRecaculate);

			m_rangebox.dXmax = (m_rangebox.dXmax < featureBox.dXmax) ? featureBox.dXmax : m_rangebox.dXmax;
			m_rangebox.dXmin = (m_rangebox.dXmin > featureBox.dXmin) ? featureBox.dXmin : m_rangebox.dXmin;
			m_rangebox.dYmax = (m_rangebox.dYmax < featureBox.dYmax) ? featureBox.dYmax : m_rangebox.dYmax;
			m_rangebox.dYmin = (m_rangebox.dYmin > featureBox.dYmin) ? featureBox.dYmin : m_rangebox.dYmin;
		}
	}

	return m_rangebox;
}

void CGeoLayer::Display(CDC* pDC)
{
	for (size_t i = 0; i < m_vecFeature.size(); i ++)
	{
		CGeoFeature* pFeature = m_vecFeature.at(i);
		if (pFeature)
		{
			pFeature->Display(pDC);
		}
	}
}


/////////////////////////////////////////////
//	CGeoMap
/////////////////////////////////////////////
CGeoMap::CGeoMap(std::string strMapName) : m_strMapName(strMapName)
{
}

CGeoMap::~CGeoMap(void)
{
	DeleteAll();
}

CGeoLayer* CGeoMap::GetLayer(std::string strLayerName)
{
	for (size_t i = 0; i < m_vecLayer.size(); i ++)
	{
		CGeoLayer* pLayer = m_vecLayer.at(i);
		if (pLayer && pLayer->GetName().compare(strLayerName) == 0)
		{
			return pLayer;
		}
	}

	CGeoLayer* pLayer = new CGeoLayer(strLayerName);
	if (NULL != pLayer)
	{
		m_vecLayer.push_back(pLayer);
		return pLayer;
	}

	return NULL;
}

RangeBox CGeoMap::GetRangeBox(bool bRecaculate/* = false*/)
{
	if (bRecaculate)
	{
		RangeBox layerBox;
		for (size_t i = 0; i < m_vecLayer.size(); i ++)
		{
			CGeoLayer* pLayer = (CGeoLayer*)m_vecLayer.at(i);
			if (NULL == pLayer) continue;
			layerBox = pLayer->GetRangeBox(bRecaculate);

			m_rangebox.dXmax = (m_rangebox.dXmax < layerBox.dXmax) ? layerBox.dXmax : m_rangebox.dXmax;
			m_rangebox.dXmin = (m_rangebox.dXmin > layerBox.dXmin) ? layerBox.dXmin : m_rangebox.dXmin;
			m_rangebox.dYmax = (m_rangebox.dYmax < layerBox.dYmax) ? layerBox.dYmax : m_rangebox.dYmax;
			m_rangebox.dYmin = (m_rangebox.dYmin > layerBox.dYmin) ? layerBox.dYmin : m_rangebox.dYmin;
		}
	}
	
	return m_rangebox;
}

void CGeoMap::Display(CDC* pDC)
{
	if (NULL == pDC) return;

	for (size_t i = 0; i < m_vecLayer.size(); i ++)
	{
		CGeoLayer* pLayer = m_vecLayer.at(i);
		if (pLayer)
		{
			pLayer->Display(pDC);
		}
	}
}

void CGeoMap::Reset()
{
	DeleteAll();
	m_dScale = 1;
	m_rangebox.dXmin = m_rangebox.dYmin = 1E20;
	m_rangebox.dXmax = m_rangebox.dYmax = -1E20;
}
void CGeoMap::DeleteAll()
{
	for (size_t i = 0; i < m_vecLayer.size(); i ++)
	{
		CGeoLayer* pLayer = m_vecLayer.at(i);
		if (pLayer)
		{
			delete pLayer;
			pLayer = NULL;
		}
	}

	m_vecLayer.clear();
}
